package org.fast.easy.framework.web.advice;

import org.fast.easy.core.domain.result.R;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.jdbc.BadSqlGrammarException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingRequestHeaderException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.fast.easy.core.util.StringUtils;

/**
 * 全局异常拦截 统一API处理返回json数据响应
 * 使用RestControllerAdvice注解 即可将异常以JSON数据的形式传递给前端 其实就是 Responsebody 与 ControllerAdvice 的结合
 * 注意：增强器上要加上注解@ResponseBody、@ControllerAdvice，不加@ResponseBody会有死循环的问题)
 * @author YanMing
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionErrorHandler {

    private static final String ERROR_MESSAGE = "服务器异常[{}]，请联系管理员！";

    /**
     * 404异常处理
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public R handleNoHandlerFoundException(NoHandlerFoundException ex){
        log.error("路径不存在：",ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"路径不存在"));
    }
    /**
     * Headers参数校验异常
     */
    @ExceptionHandler(value = MissingRequestHeaderException.class)
    public R missingRequestHeaderException( MissingRequestHeaderException ex) {
        log.error("Headers参数校验异常：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"Headers参数校验异常"));
    }


    /**
     * 输入参数校验异常
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R<List<String>> notValidExceptionHandler( MethodArgumentNotValidException ex) {

        List<String> errorList = new ArrayList<>();
        List<ObjectError> list =ex.getAllErrors();
        for (ObjectError error : list) {
            String defaultMessage = error.getDefaultMessage();
            if(StringUtils.isNotBlank(defaultMessage)){
                errorList.add(defaultMessage);
            }
        }
        log.error("自定义验证异常：{} {} {}", ex.getMessage(), ex, errorList);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"输入参数校验异常"));
    }


    /**
     * 自定义验证异常
     */
    @ExceptionHandler(BindException.class)
    public R validatedBindException(BindException ex)
    {
        log.error("自定义验证异常：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"自定义验证异常"));
    }
    /** 动态库不存在 */
    @ExceptionHandler(UnsatisfiedLinkError.class)
    public R unsatisfiedLinkError(UnsatisfiedLinkError ex) {
        log.error("动态库不存在：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"动态库不存在"));
    }

    /** 运行时异常 */
    @ExceptionHandler(RuntimeException.class)
    public R runtimeExceptionHandler(RuntimeException ex) {
        log.error("运行时异常：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"运行时异常"));
    }

    /** 空指针异常 */
    @ExceptionHandler(NullPointerException.class)
    public R nullPointerExceptionHandler(NullPointerException ex) {
        log.error("空指针异常：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"空指针异常"));
    }

    /** 类型转换异常 */
    @ExceptionHandler(ClassCastException.class)
    public R classCastExceptionHandler(ClassCastException ex) {
        log.error("类型转换异常：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"类型转换异常"));
    }
    /** 文件未找到异常 */
    @ExceptionHandler(FileNotFoundException.class)
    public R fileNotFoundException(FileNotFoundException ex) {
        log.error("文件未找到异常：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"文件未找到异常"));
    }
    /** 数字格式异常 */
    @ExceptionHandler(NumberFormatException.class)
    public R numberFormatException(NumberFormatException ex) {
        log.error("数字格式异常：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"数字格式异常"));
    }
    /** 安全异常 */
    @ExceptionHandler(SecurityException.class)
    public R securityException(SecurityException ex) {
        log.error("Security安全异常(如果安全管理器存在并且其 checkLink 方法不允许加载指定的动态库)：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"Security安全异常"));
    }
    /** sql异常 */
    @ExceptionHandler(SQLException.class)
    public R sqlException(SQLException ex) {
        log.error("SQL异常：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"SQL异常"));
    }
    /** 类型不存在异常 */
    @ExceptionHandler(TypeNotPresentException.class)
    public R typeNotPresentException(TypeNotPresentException ex) {
        log.error("类型不存在异常：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"类型不存在异常"));
    }

    /** IO异常 */
    @ExceptionHandler(IOException.class)
    public R ioExceptionHandler(IOException ex) {
        log.error("IO异常：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"IO异常"));
    }

    /** 未知方法异常 */
    @ExceptionHandler(NoSuchMethodException.class)
    public R noSuchMethodExceptionHandler(NoSuchMethodException ex) {
        log.error("未知方法异常：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"未知方法异常"));
    }

    /** 数组越界异常 */
    @ExceptionHandler(IndexOutOfBoundsException.class)
    public R indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) {
        log.error("数组越界异常：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"数组越界异常"));
    }

    /**
     * sql语法错误异常
     * */

    @ExceptionHandler(BadSqlGrammarException.class)
    public R badSqlGrammarException(BadSqlGrammarException ex) {
        log.error("SQL语法错误异常：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"SQL语法错误异常"));
    }

    /** 无法注入bean异常 */

    @ExceptionHandler(NoSuchBeanDefinitionException.class)
    public R noSuchBeanDefinitionException(NoSuchBeanDefinitionException ex) {
        log.error("无法注入bean异常 ：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"无法注入bean异常"));
    }



    /** 除数不能为0 */
    @ExceptionHandler({ArithmeticException.class})
    public R arithmeticException(ArithmeticException ex) {
        log.error("除数不能为0：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"除数不能为0"));
    }

    /** http type错误 */
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public R httpType(HttpRequestMethodNotSupportedException ex) {
        log.error("http type：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"HTTP类型错误"));
    }


    /** 400错误 */
    @ExceptionHandler({HttpMessageNotReadableException.class})
    public R requestNotReadable(HttpMessageNotReadableException ex) {
        log.error("400错误..requestNotReadable：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"400"));
    }

    /** 400错误 */
    @ExceptionHandler({TypeMismatchException.class})
    public R requestTypeMismatch(TypeMismatchException ex) {
        log.error("400错误..TypeMismatchException：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"400"));
    }

    /** 500错误 */
    @ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
    public R server500(RuntimeException ex) {
        log.error("500错误：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"500"));
    }

    /** 栈溢出 */
    @ExceptionHandler({StackOverflowError.class})
    public R requestStackOverflow(StackOverflowError ex) {
        log.error("栈溢出：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"栈溢出"));
    }

    /**
     *  默认异常处理，前面未处理
     */
    @ExceptionHandler(value = Throwable.class)
    public R defaultHandler( Exception ex)  {
        log.error("500错误：{} {}", ex.getMessage(), ex);
        return R.fail(StringUtils.format(ERROR_MESSAGE,"500"));
    }



}

